package tp.pr5.instructions;

import tp.pr5.NavigationModule;
import tp.pr5.RobotEngine;
import tp.pr5.instructions.exceptions.InstructionExecutionException;
import tp.pr5.instructions.exceptions.WrongInstructionFormatException;
import tp.pr5.items.Item;
import tp.pr5.items.ItemContainer;

public class DropInstruction extends UndoAble {
	private String objeto;
	private NavigationModule nvm;
	private RobotEngine rbt;
	private ItemContainer rbtCont;
	
	/*
	 * Parameters for the undo
	 */
	private Item lastObject;
	
	/**
	 * constructor that receives the object Ã�D
	 * @param objeto
	 */
	public DropInstruction(String objeto) {
		this.objeto = objeto;
	}
	/**
	 * default constructor
	 */
	public DropInstruction(){
		this.objeto = null;
	}
	/**
	 * parses the instruction from the string given
	 */
	@Override
	public Instruction parse(String cad) throws WrongInstructionFormatException {
		String[] lineArr = cad.trim().replaceAll(" +", " ").split(" ");	//parte la cadena introducida en palabras
		String accion = "";
		String id = "";
		if(lineArr.length>=1) accion = lineArr[0]; //si existe alguna palabra, la primera serÃ¡ la acciÃ³n
		if(lineArr.length==2) id = lineArr[1]; //si hay mÃ¡s de una palabra, la segunda serÃ¡ la rotaciÃ³n	
		
		if(accion.equalsIgnoreCase("DROP") || accion.equalsIgnoreCase("SOLTAR")){//si la acciÃ³n introducida es DROP
			if(id != "") return new DropInstruction(id);
			else throw new WrongInstructionFormatException();
		}else{
			throw new WrongInstructionFormatException();
		}	
		
	}
	/**
	 * returns instruction help string
	 */
	@Override
	public String getHelp() {
		return "     DROP|SOLTAR <ITEM>";
	}
	/**
	 * sets the needed variables
	 */
	@Override
	public void configureContext(RobotEngine engine,
			NavigationModule navigation, ItemContainer robotContainer) {
		this.nvm = navigation;
		this.rbt = engine;
		this.rbtCont = robotContainer;
	}
	/**
	 * executes the instruction if possible
	 */
	@Override
	public void execute() throws InstructionExecutionException {		
		ItemContainer icSelf = this.rbtCont;
		if(!icSelf.containsItem(objeto)){
			//this.rbt.emitRoboySays("You do not have any "+objeto+".");
			throw new InstructionExecutionException("You do not have any "+objeto+".");
		}
		if(this.nvm.getCurrentPlace().getInventory().containsItem(objeto)){
			//this.rbt.emitRoboySays("There is already "+objeto+" in this place.");
			throw new InstructionExecutionException("There is already "+objeto+" in this place.");
		}		
		Item ob = icSelf.pickItem(objeto);			
		this.nvm.dropItemAtCurrentPlace(ob);
		this.lastObject = ob;
		this.rbt.emitInventoryChanged("");
		this.rbt.emitRoboySays("WALL·E says: Great! I have dropped "+ob.getId());
		
	}
	/**
	 * returns true if the instruction can be undone
	 */
	@Override
	public boolean isUndoAble() {
		return true;
	}
	/**
	 * reverts the last instruction
	 * @throws InstructionExecutionException 
	 */
	public void undo() {
		ItemContainer icPlace = this.nvm.getCurrentPlace().getInventory();		
		ItemContainer icSelf = this.rbtCont;		
		if(icPlace.containsItem(this.lastObject.getId()) ){
			icSelf.addItem(this.nvm.pickItemFromCurrentPlace(this.lastObject.getId()));
			this.rbt.emitInventoryChanged("");			
		}
	}

}
